/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */


package com.taptech.doufu.ui.view.weex;

import android.annotation.SuppressLint;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebView;
import android.widget.FrameLayout;
import android.widget.ImageView;

import com.taobao.weex.IWXRenderListener;
import com.taobao.weex.WXSDKInstance;
import com.taobao.weex.annotation.Component;
import com.taobao.weex.common.Constants;
import com.taobao.weex.common.WXPerformance;
import com.taobao.weex.common.WXRenderStrategy;
import com.taobao.weex.ui.action.BasicComponentData;
import com.taobao.weex.ui.component.NestedContainer;
import com.taobao.weex.ui.component.WXComponent;
import com.taobao.weex.ui.component.WXComponentProp;
import com.taobao.weex.ui.component.WXDiv;
import com.taobao.weex.ui.component.WXVContainer;
import com.taobao.weex.utils.WXLogUtils;
import com.taobao.weex.utils.WXUtils;
import com.taobao.weex.utils.WXViewUtils;
import com.taptech.doufu.weex.TFWXUtil;

@Component(lazyload = false)
public class TFEmbed extends WXDiv implements WXSDKInstance.OnInstanceVisibleListener,NestedContainer {

    public static final String ITEM_ID = "itemId";

    private String src;
    private WXSDKInstance mNestedInstance;
    private static int ERROR_IMG_WIDTH = (int) WXViewUtils.getRealPxByWidth(270,750);
    private static int ERROR_IMG_HEIGHT = (int) WXViewUtils.getRealPxByWidth(260,750);

    private boolean mIsVisible = true;
    private EmbedRenderListener mListener;

    public TFEmbed(WXSDKInstance instance, WXVContainer parent, BasicComponentData basicComponentData) {
        super(instance, parent, basicComponentData);
        mListener = new EmbedRenderListener(this);

        ERROR_IMG_WIDTH = (int) WXViewUtils.getRealPxByWidth(270,instance.getInstanceViewPortWidth());
        ERROR_IMG_HEIGHT = (int) WXViewUtils.getRealPxByWidth(260,instance.getInstanceViewPortWidth());
        if(instance instanceof EmbedManager) {
            Object itemId = parent.getAttrs().get(ITEM_ID);
            if (itemId != null) {
                ((EmbedManager) instance).putEmbed(itemId.toString(), this);
            }
        }
    }

    public interface EmbedManager {
        TFEmbed getEmbed(String itemId);
        void putEmbed(String itemId,TFEmbed comp);
    }

    public static class FailToH5Listener extends ClickToReloadListener {
        @SuppressLint("SetJavaScriptEnabled")
        @Override
        public void onException(NestedContainer comp, String errCode, String msg) {
            //downgrade embed
            if( errCode != null && comp instanceof TFEmbed && errCode.startsWith("1|")) {
                ViewGroup container = comp.getViewContainer();
                WebView webView = new WebView(container.getContext());
                ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
                webView.setLayoutParams(params);
                webView.getSettings().setJavaScriptEnabled(true);

                //WebView Remote Code Execution Vulnerability
                webView.removeJavascriptInterface("searchBoxJavaBridge_");
                webView.removeJavascriptInterface("accessibility");
                webView.removeJavascriptInterface("accessibilityTraversal");
                webView.getSettings().setSavePassword(false);

                container.removeAllViews();
                container.addView(webView);
                webView.loadUrl(((TFEmbed) comp).src);
            }else{
                super.onException(comp,errCode,msg);
            }
        }
    }

    /**
     * Default event listener.
     */
    public static class ClickToReloadListener implements OnNestedInstanceEventListener {
        @Override
        public void onException(NestedContainer container, String errCode, String msg) {
            if (TextUtils.equals(errCode, "") && container instanceof TFEmbed) {
                final TFEmbed comp = ((TFEmbed)container);
                final ImageView imageView = new ImageView(comp.getContext());
//                imageView.setImageResource(R.drawable.error);
                FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(ERROR_IMG_WIDTH, ERROR_IMG_HEIGHT);
                layoutParams.gravity = Gravity.CENTER;
                imageView.setLayoutParams(layoutParams);
                imageView.setScaleType(ImageView.ScaleType.FIT_XY);
                imageView.setAdjustViewBounds(true);
                imageView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        imageView.setOnClickListener(null);
                        imageView.setEnabled(false);
                        comp.loadContent();
                    }
                });
                FrameLayout hostView = comp.getHostView();
                hostView.removeAllViews();
                hostView.addView(imageView);
                WXLogUtils.e("TFEmbed", "NetWork failure :" + errCode + ",\n error message :" + msg);
            }
        }

        @Override
        public boolean onPreCreate(NestedContainer comp, String src) {
            return true;
        }

        @Override
        public String transformUrl(String origin) {
            return origin;
        }

        @Override
        public void onCreated(NestedContainer comp, WXSDKInstance nestedInstance) {

        }
    }

    static class EmbedRenderListener implements IWXRenderListener {
        TFEmbed mComponent;
        OnNestedInstanceEventListener mEventListener;

        EmbedRenderListener(TFEmbed comp) {
            mComponent = comp;
            mEventListener = new ClickToReloadListener();
        }

        @Override
        public void onViewCreated(WXSDKInstance instance, View view) {
            FrameLayout hostView = mComponent.getHostView();
            hostView.removeAllViews();
            hostView.addView(view);
        }

        @Override
        public void onRenderSuccess(WXSDKInstance instance, int width, int height) {

        }

        @Override
        public void onRefreshSuccess(WXSDKInstance instance, int width, int height) {

        }

        @Override
        public void onException(WXSDKInstance instance, String errCode, String msg) {
            if (mEventListener != null) {
                mEventListener.onException(mComponent, errCode, msg);
            }
        }
    }

//    @Deprecated
//    public TFEmbed(WXSDKInstance instance, WXDomObject dom, WXVContainer parent, String instanceId, boolean isLazy) {
//        this(instance,dom,parent);
//    }
//
//    public TFEmbed(WXSDKInstance instance, WXDomObject node, WXVContainer parent) {
//        super(instance, node, parent);
//        mListener = new EmbedRenderListener(this);
//
//        ERROR_IMG_WIDTH = (int) WXViewUtils.getRealPxByWidth(270,instance.getInstanceViewPortWidth());
//        ERROR_IMG_HEIGHT = (int) WXViewUtils.getRealPxByWidth(260,instance.getInstanceViewPortWidth());
//        if(instance instanceof EmbedManager) {
//            Object itemId = node.getAttrs().get(ITEM_ID);
//            if (itemId != null) {
//                ((EmbedManager) instance).putEmbed(itemId.toString(), this);
//            }
//        }
//    }

    @Override
    public void setOnNestEventListener(NestedContainer.OnNestedInstanceEventListener listener){
        mListener.mEventListener = listener;
    }

    @Override
    public ViewGroup getViewContainer() {
        return getHostView();
    }

    @Override
    protected boolean setProperty(String key, Object param) {
        switch (key) {
            case Constants.Name.SRC:
                String src = WXUtils.getString(param,null);
                if (src != null)
                    setSrc(src);
                return true;
        }
        return super.setProperty(key, param);
    }

    @Override
    public void renderNewURL(String url) {
        src = url;
        loadContent();
    }

    @Override
    public void reload() {
        if (!TextUtils.isEmpty(src)) {
            loadContent();
        }
    }

    public String getOriginUrl() {
        return originUrl;
    }

    public void setOriginUrl(String originUrl) {
        this.originUrl = originUrl;
    }

    private String originUrl;

    @WXComponentProp(name = Constants.Name.SRC)
    public void setSrc(String src) {
        originUrl=src;
        this.src = src;
        if (mNestedInstance != null) {
            mNestedInstance.destroy();
            mNestedInstance = null;
        }
        if (mIsVisible && !TextUtils.isEmpty(this.src)) {
            loadContent();
        }
    }
    public String getSrc() {
        return src;
    }

    /**
     * Load embed content, default behavior is create a nested instance.
     */
    protected void loadContent(){
        mNestedInstance = createInstance();
        if(mListener != null && mListener.mEventListener != null){
            if(!mListener.mEventListener.onPreCreate(this,src)){
                //cancel render
                mListener.mEventListener.onCreated(this, mNestedInstance);
            }
        }
    }
    /**
     * 获取Url
     */
    private String getUrl(String url){



            return TFWXUtil.handleWXUrl(url);

    }

    private WXSDKInstance createInstance() {
        WXSDKInstance sdkInstance = getInstance().createNestedInstance(this);
        getInstance().addOnInstanceVisibleListener(this);
        sdkInstance.registerRenderListener(mListener);

        String url=src;
        if(mListener != null && mListener.mEventListener != null){
            url=mListener.mEventListener.transformUrl(src);
            if(!mListener.mEventListener.onPreCreate(this,src)){
                //cancel render
                return null;
            }
        }

        if(TextUtils.isEmpty(url)){//WX_USER_INTERCEPT_ERROR
            mListener.mEventListener.onException(this,"","degradeToH5");
            return sdkInstance;
        }

        ViewGroup.LayoutParams layoutParams = getHostView().getLayoutParams();  //qlx fixed

        url = this.getUrl(url);
        if (url.startsWith("http") == true){
            sdkInstance.renderByUrl(WXPerformance.DEFAULT, url, null, null, WXRenderStrategy.APPEND_ASYNC);

        }else {
            sdkInstance.render("TF",url, null , null, WXRenderStrategy.APPEND_ASYNC);
        }//qlx fixed end


//        sdkInstance.renderByUrl(WXPerformance.DEFAULT,
//                url,
//                null, null, layoutParams.width,
//                layoutParams.width
//                WXRenderStrategy.APPEND_ASYNC);






        return sdkInstance;
    }

    @Override
    public void setVisibility(String visibility) {
        super.setVisibility(visibility);
        boolean visible = TextUtils.equals(visibility, Constants.Value.VISIBLE);
        if (!TextUtils.isEmpty(src) && visible) {
            if (mNestedInstance == null) {
                loadContent();
            } else {
                mNestedInstance.onViewAppear();
            }
        }

        if (!visible) {
            if (mNestedInstance != null) {
                mNestedInstance.onViewDisappear();
            }
        }
        mIsVisible = visible;
    }

    @Override
    public void destroy() {
        super.destroy();
        if (mNestedInstance != null) {
            mNestedInstance.destroy();
            mNestedInstance = null;
        }
        src = null;
        if (getInstance() != null) {
            getInstance().removeOnInstanceVisibleListener(this);
        }
    }

    @Override
    public void onAppear() {
        //appear event from root instance will not trigger visibility change
        if(mIsVisible && mNestedInstance != null){
            WXComponent comp = mNestedInstance.getRootComponent();
            if(comp != null)
                comp.fireEvent(Constants.Event.VIEWAPPEAR);
        }
    }

    @Override
    public void onDisappear() {
        //appear event from root instance will not trigger visibility change
        if(mIsVisible && mNestedInstance != null){
            WXComponent comp = mNestedInstance.getRootComponent();
            if(comp != null)
                comp.fireEvent(Constants.Event.VIEWDISAPPEAR);
        }
    }

    @Override
    public void onActivityStart() {
        super.onActivityStart();
        if (mNestedInstance != null) {
            mNestedInstance.onActivityStart();
        }
    }

    @Override
    public void onActivityResume() {
        super.onActivityResume();
        if (mNestedInstance != null) {
            mNestedInstance.onActivityResume();
        }
    }

    @Override
    public void onActivityPause() {
        super.onActivityPause();
        if (mNestedInstance != null) {
            mNestedInstance.onActivityPause();
        }
    }

    @Override
    public void onActivityStop() {
        super.onActivityStop();
        if (mNestedInstance != null) {
            mNestedInstance.onActivityStop();
        }
    }

    @Override
    public void onActivityDestroy() {
        super.onActivityDestroy();
        if (mNestedInstance != null) {
            mNestedInstance.onActivityDestroy();
        }
    }
}
